package com.lmh.graphdisease.service.impl;

import cn.hutool.core.date.chinese.LunarFestival;
import com.lmh.graphdisease.entity.*;
import com.lmh.graphdisease.repository.DiseaseRepository;
import com.lmh.graphdisease.service.DiseaseService;
import com.lmh.graphdisease.utils.AnswerUtil;
import com.lmh.graphdisease.utils.JieBaUtil;
import com.lmh.graphdisease.utils.MatchEntityCastUtil;
import com.lmh.graphdisease.utils.QuestionUtil;
import com.lmh.graphdisease.vo.FeatureWordsVO;
import org.ahocorasick.trie.Trie;
import org.neo4j.driver.internal.value.NodeValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Node;
import org.w3c.dom.ls.LSInput;

import java.io.IOException;
import java.util.*;

/**
 * @author lmh
 * @desc
 * @date 2023/3/6
 */
@Service
public class DiseaseServiceImpl implements DiseaseService {

    @Autowired
    DiseaseRepository diseaseRepository;

    @Override
    public DiseaseEntity getDiseaseEntityByName(String name) {
        return diseaseRepository.findDiseaseEntityByName(name);
    }

    @Override
    public Map<String, Integer> getCloudByName(String name) {
        DiseaseEntity curDisease = getDiseaseEntityByName(name);
        String curAboutDisease = curDisease.getCurAbout();
        List<String> sentences = JieBaUtil.getSentences(curAboutDisease);
        Map<String,Integer> result = JieBaUtil.getWordsByJieBaUtil(sentences);
        return result;
    }

    @Override
    public List<CheckEntity> getCheckByDisease(String name, int num) {
        List<NodeValue> getResult = diseaseRepository.getNeedCheck(name,num);
        List<CheckEntity> checkEntities = new ArrayList<>();
        for (NodeValue nodeValue:getResult){
            checkEntities.add(MatchEntityCastUtil.MatchToCheckEntity(nodeValue));
        }
        return checkEntities;
    }
    @Override
    public List<DepartmentEntity> getDepartmentByDisease(String name, int num) {
        List<NodeValue> getResult = diseaseRepository.getBelongTo(name,num);
        List<DepartmentEntity> departmentEntities = new ArrayList<>();
        for (NodeValue nodeValue:getResult){
            departmentEntities.add(MatchEntityCastUtil.MatchToDepartmentEntity(nodeValue));
        }
        return departmentEntities;
    }

    @Override
    public List<DrugEntity> getDrugByDisease(String name, int num) {
        List<NodeValue> getResult = diseaseRepository.getCommonDrug(name,num);
        List<DrugEntity> drugEntities = new ArrayList<>();
        for (NodeValue nodeValue:getResult){
            drugEntities.add(MatchEntityCastUtil.MatchToDrugEntity(nodeValue));
        }
        return drugEntities;
    }

    @Override
    public Map<String,List<FoodEntity>> getFoodByDisease(String name, int num) {
        List<NodeValue> getResult1 = diseaseRepository.getDoEat(name,num);
        List<NodeValue> getResult2 = diseaseRepository.getNoEat(name,num);
        List<NodeValue> getResult3 = diseaseRepository.getRecommandEat(name,num);
        List<FoodEntity> foodEntities1 = new ArrayList<>();
        List<FoodEntity> foodEntities2 = new ArrayList<>();
        List<FoodEntity> foodEntities3 = new ArrayList<>();
        for (NodeValue nodeValue:getResult1){
            foodEntities1.add(MatchEntityCastUtil.MatchToFoodEntity(nodeValue));
        }
        for (NodeValue nodeValue:getResult2){
            foodEntities2.add(MatchEntityCastUtil.MatchToFoodEntity(nodeValue));
        }
        for (NodeValue nodeValue:getResult3){
            foodEntities3.add(MatchEntityCastUtil.MatchToFoodEntity(nodeValue));
        }
        Map<String,List<FoodEntity>> result = new HashMap<>();
        result.put("doeat",foodEntities1);
        result.put("noteat",foodEntities2);
        result.put("receat",foodEntities3);
        return result;
    }

    @Override
    public List<SymptomEntity> getSymptomByDisease(String name, int num) {
        List<NodeValue> getResult = diseaseRepository.getHasSymptom(name,num);
        List<SymptomEntity> symptomEntities = new ArrayList<>();
        for (NodeValue nodeValue:getResult){
            symptomEntities.add(MatchEntityCastUtil.MatchToSymptomEntity(nodeValue));
        }
        return symptomEntities;
    }


    @Override
    public List<DiseaseEntity> getAllDisease() {
        return diseaseRepository.findAll();
    }

    @Override
    public Map<String, Object> getNumDisease(int page,int size) {
        Map<String,Object> result = new HashMap<>();
        int curSkipNum = (page - 1) * size;
        List<DiseaseEntity> result1 = diseaseRepository.getNumDisease(curSkipNum,size);
        if(result1 == null) return null;
        Set<String> diseaseSet = new HashSet<>();
        Set<String> departmentSet = new HashSet<>();
        Set<String> checkSet = new HashSet<>();
        Set<String> drugSet = new HashSet<>();
        Set<String> foodSet = new HashSet<>();
        Set<String> symptomSet = new HashSet<>();
        List<String> relationShips = new ArrayList<>();
        for (DiseaseEntity d:result1){
            String name = d.getName();
            String id = d.getId()+"";
            String idName = d.getId() + "::" +name;
            diseaseSet.add(idName);
            List<CheckEntity> checkList = getCheckByDisease(name,5);
            for (CheckEntity cur:checkList){
                String curName = cur.getName();
                checkSet.add(curName);
                relationShips.add(id + "-*-" + "需要检查" + "-*-" + curName);
            }
            List<DepartmentEntity> departmentList = getDepartmentByDisease(name,5);
            for (DepartmentEntity cur:departmentList){
                String curName = cur.getName();
                departmentSet.add(curName);
                relationShips.add(id + "-*-" + "所属科室" + "-*-" + curName);
            }
            List<DrugEntity> drugList = getDrugByDisease(name,5);
            for (DrugEntity cur:drugList){
                String curName = cur.getName();
                drugSet.add(curName);
                relationShips.add(id + "-*-" + "推荐药物" + "-*-" + curName);
            }
            List<SymptomEntity> symptomList = getSymptomByDisease(name,5);
            for (SymptomEntity cur:symptomList){
                String curName = cur.getName();
                symptomSet.add(curName);
                relationShips.add(id + "-*-" + "表现症状" + "-*-" + curName);
            }
            List<FoodEntity> foodList = getFoodByDisease(name,5).get("doeat");
            for (FoodEntity cur:foodList){
                String curName = cur.getName();
                foodSet.add(curName);
                relationShips.add(id + "-*-" + "推荐食物" + "-*-" + curName);
            }
        }
        result.put("disease",diseaseSet);
        result.put("department",departmentSet);
        result.put("check",checkSet);
        result.put("drug",drugSet);
        result.put("food",foodSet);
        result.put("symptom",symptomSet);
        result.put("relationships",relationShips);
        return result;
    }

    @Override
    public Map<String, Object> getOneDisease(String name1) {
        Map<String,Object> result = new HashMap<>();
        DiseaseEntity diseaseEntity = diseaseRepository.findDiseaseEntityByName(name1);
        if(diseaseEntity == null) return null;

        Set<String> diseaseSet = new HashSet<>();
        Set<String> departmentSet = new HashSet<>();
        Set<String> checkSet = new HashSet<>();
        Set<String> drugSet = new HashSet<>();
        Set<String> foodSet = new HashSet<>();
        Set<String> symptomSet = new HashSet<>();
        List<String> relationShips = new ArrayList<>();
            String name = diseaseEntity.getName();
            String id = diseaseEntity.getId()+"";
            String idName = diseaseEntity.getId() + "::" +name;
            diseaseSet.add(idName);
            List<CheckEntity> checkList = getCheckByDisease(name,5);
            for (CheckEntity cur:checkList){
                String curName = cur.getName();
                checkSet.add(curName);
                relationShips.add(id + "-*-" + "需要检查" + "-*-" + curName);
            }
            List<DepartmentEntity> departmentList = getDepartmentByDisease(name,5);
            for (DepartmentEntity cur:departmentList){
                String curName = cur.getName();
                departmentSet.add(curName);
                relationShips.add(id + "-*-" + "所属科室" + "-*-" + curName);
            }
            List<DrugEntity> drugList = getDrugByDisease(name,5);
            for (DrugEntity cur:drugList){
                String curName = cur.getName();
                drugSet.add(curName);
                relationShips.add(id + "-*-" + "推荐药物" + "-*-" + curName);
            }
            List<SymptomEntity> symptomList = getSymptomByDisease(name,5);
            for (SymptomEntity cur:symptomList){
                String curName = cur.getName();
                symptomSet.add(curName);
                relationShips.add(id + "-*-" + "表现症状" + "-*-" + curName);
            }
            List<FoodEntity> foodList = getFoodByDisease(name,5).get("doeat");
            for (FoodEntity cur:foodList){
                String curName = cur.getName();
                foodSet.add(curName);
                relationShips.add(id + "-*-" + "推荐食物" + "-*-" + curName);
            }

        result.put("disease",diseaseSet);
        result.put("department",departmentSet);
        result.put("check",checkSet);
        result.put("drug",drugSet);
        result.put("food",foodSet);
        result.put("symptom",symptomSet);
        result.put("relationships",relationShips);
        return result;
    }

    /**
     *@author lmh
     *@date 2023/3/18
     *@desc 辅助诊断功能实现
     */
    @Override
    public String getRobotAnswer(String askText){
        StringBuilder sb = new StringBuilder();
        int number = 10;
        /**
         *@author lmh
         *@date 2023/3/26
         *@desc QuestionUtil中方法的使用
         * entityDict：{disease=[苯中毒, 多动症, 小儿麻痹症]。。。}
         * questionTypeList：[disease_cureprob]
         */
        FeatureWordsVO featureWordsVO = QuestionUtil.getFeatureWordsFromTXT();
        //构建字典树
        Trie trie = QuestionUtil.buildACTreeFromVO(featureWordsVO);
        Map<String,String> map = QuestionUtil.useACTreeToQuestion(trie,featureWordsVO,askText);
        if(map.isEmpty()){
            return "对不起，我没有听懂，请您换种方式进行询问。";
        }
        //转化、整合一下
        Map<String,List<String>> entityDict = QuestionUtil.getEntityDict(map);
        //获取问句类型List
        List<String> questionTypeList = QuestionUtil.getQustionTypes(askText,map);
        /**
         *@author lmh
         *@date 2023/3/26
         *@desc 从数据库中查询
         */
        for (String questionType:questionTypeList){
            Map<String,List<String>> sqlResult = new HashMap<>();
            //目前只能问一种疾病
            String[] curType = questionType.split("_");
            String askDisease = entityDict.get("disease").get(0);//先只查找一个
            DiseaseEntity diseaseEntity = diseaseRepository.findDiseaseEntityByName(askDisease);
            List<String> diseaseList = new ArrayList<>();
            diseaseList.add(diseaseEntity.getName());
            sqlResult.put("disease_name",diseaseList);
            //长度为2
            if(curType.length == 2){
//                System.out.println(curType[0]);//*****
                if(Objects.equals(curType[0], "disease") && !Objects.equals(curType[1], "disease")){//“disease_***”的类型
//                if(entityDict.containsKey("disease") && !entityDict.get("disease").isEmpty()){
//                }
                    switch (curType[1]){
                        case "symptom":
                            List<NodeValue> diseaseSymptom = diseaseRepository.getHasSymptom(askDisease,number);
                            List<String> symptomList = new ArrayList<>();
                            for (NodeValue nodeValue:diseaseSymptom){
                                SymptomEntity symptomEntity = MatchEntityCastUtil.MatchToSymptomEntity(nodeValue);
                                symptomList.add(symptomEntity.getName());
                            }
                            sqlResult.put("disease_symptom",symptomList);
                            break;
                        case "cause":
                            List<String> causeList = new ArrayList<>();
                            causeList.add(diseaseEntity.getCause());
                            sqlResult.put("disease_cause",causeList);
                            break;
                        case "prevent":
                            List<String> preventList = new ArrayList<>();
                            preventList.add(diseaseEntity.getPrevent());
                            sqlResult.put("disease_prevent",preventList);
                            break;
                        case "check":
                            List<NodeValue> diseaseCheck = diseaseRepository.getNeedCheck(askDisease,number);
                            List<String> checkList = new ArrayList<>();
                            for (NodeValue nodeValue:diseaseCheck){
                                CheckEntity checkEntity = MatchEntityCastUtil.MatchToCheckEntity(nodeValue);
                                checkList.add(checkEntity.getName());
                            }
                            sqlResult.put("disease_check",checkList);
                            break;
                        case "lasttime":
                            List<String> lasttimeList = new ArrayList<>();
                            lasttimeList.add(diseaseEntity.getCure_lasttime());
                            sqlResult.put("disease_lasttime",lasttimeList);
                            break;
                        case "cureway":
                            sqlResult.put("disease_cureway",diseaseEntity.getCure_way());
                            break;
                        case "cureprob":
                            List<String> cureprobList = new ArrayList<>();
                            cureprobList.add(diseaseEntity.getCured_prob());
                            sqlResult.put("disease_cureprob",cureprobList);
                            break;
                        case "easyget":
                            List<String> easygetList = new ArrayList<>();
                            easygetList.add(diseaseEntity.getEasy_get());
                            sqlResult.put("disease_easyget",easygetList);
                            break;
                        case "desc":
                            List<String> descList = new ArrayList<>();
                            descList.add(diseaseEntity.getDesc());
                            sqlResult.put("disease_desc",descList);
                            break;
                        case "acompany":
                            List<NodeValue> diseaseAcompany = diseaseRepository.getAcompanyWith(askDisease,number);
                            List<String> acompanyList = new ArrayList<>();
                            for (NodeValue nodeValue:diseaseAcompany){
                                DiseaseEntity diseaseEntity1 = MatchEntityCastUtil.MatchToDiaseaseEntity(nodeValue);
                                acompanyList.add(diseaseEntity1.getName());
                            }
                            sqlResult.put("disease_acompany",acompanyList);
                            break;
                        case "drug":
                            List<NodeValue> diseaseDrug = diseaseRepository.getCommonDrug(askDisease,number);
                            List<NodeValue> diseaseDrug2 = diseaseRepository.getRecommandDrug(askDisease,number);
                            diseaseDrug.addAll(diseaseDrug2);
                            List<String> drugList = new ArrayList<>();
                            for (NodeValue nodeValue:diseaseDrug){
                                DrugEntity drugEntity = MatchEntityCastUtil.MatchToDrugEntity(nodeValue);
                                if(!drugList.contains(drugEntity.getName())){
                                    drugList.add(drugEntity.getName());
                                }
                            }
                            sqlResult.put("disease_drug",drugList);
                            break;
                    }
                }else if(!Objects.equals(curType[0], "disease") && Objects.equals(curType[1], "disease")){//"***_disease"的类型
                    List<DiseaseEntity> curDiseaseList;
                    String curKey = "";
                    if(Objects.equals(curType[0], "symptom")){
                        String symptomName = entityDict.get("symptom").get(0);
                        List<String> symptomList = new ArrayList<>();
                        symptomList.add(symptomName);
                        sqlResult.put("symptom_name",symptomList);
                        curDiseaseList = diseaseRepository.getSymptomDisease(symptomName,number);
                        curKey = "symptom_disease";
                    }else if(Objects.equals(curType[0], "drug")){
                        String drugName = entityDict.get("drug").get(0);
                        List<String> drugList = new ArrayList<>();
                        drugList.add(drugName);
                        sqlResult.put("drug_name",drugList);
                        curDiseaseList = diseaseRepository.getDrugCommonDisease(drugName,number);
                        curDiseaseList.addAll(diseaseRepository.getDrugRecommandDisease(drugName,number));
                        curKey = "drug_disease";
                    }else {
                        String checkName = entityDict.get("check").get(0);
                        List<String> checkList = new ArrayList<>();
                        checkList.add(checkName);
                        sqlResult.put("check_name",checkList);
                        curDiseaseList = diseaseRepository.getCheckDisease(checkName,number);
                        curKey = "check_disease";
                    }
                    List<String> curList = new ArrayList<>();
                    for (DiseaseEntity diseaseEntity1:curDiseaseList){
                        curList.add(diseaseEntity1.getName());
                    }
                    sqlResult.put(curKey,curList);
                }
            }else {
                //能吃、不能吃的食物；
                if(Objects.equals(curType[0], "disease")){
                    if(Objects.equals(curType[1], "not")){
                        List<NodeValue> notEatFood = diseaseRepository.getNoEat(askDisease,number);
                        List<String> notEatList = new ArrayList<>();
                        for (NodeValue nodeValue:notEatFood){
                            FoodEntity foodEntity = MatchEntityCastUtil.MatchToFoodEntity(nodeValue);
                            notEatList.add(foodEntity.getName());
                        }
                        sqlResult.put("disease_not_food",notEatList);
                    }else {
                        List<NodeValue> doEatFood = diseaseRepository.getDoEat(askDisease,number);
                        doEatFood.addAll(diseaseRepository.getRecommandEat(askDisease,number));
                        List<String> doEatList = new ArrayList<>();
                        for (NodeValue nodeValue:doEatFood){
                            FoodEntity foodEntity = MatchEntityCastUtil.MatchToFoodEntity(nodeValue);
                            if(!doEatList.contains(foodEntity.getName())){
                                doEatList.add(foodEntity.getName());
                            }
                        }
                        sqlResult.put("disease_do_food",doEatList);
                    }
                }else {//能吃、不能吃**的疾病
                    String curFoodName = entityDict.get("food_name").get(0);
                    List<String> curFoodList = new ArrayList<>();
                    curFoodList.add(curFoodName);
                    sqlResult.put("food_name",curFoodList);
                    if(Objects.equals(curType[1], "not")){
                        List<DiseaseEntity> notEatDisease = diseaseRepository.getNotFoodDisease(curFoodName,number);
                        List<String> noEatFoodDiseaseList = new ArrayList<>();
                        for (DiseaseEntity diseaseEntity1:notEatDisease){
                            noEatFoodDiseaseList.add(diseaseEntity1.getName());
                        }
                        sqlResult.put("food_not_disease",noEatFoodDiseaseList);
                    }else {
                        List<DiseaseEntity> doEatDisease = diseaseRepository.getDoFoodDisease(curFoodName,number);
                        doEatDisease.addAll(diseaseRepository.getRecommandFoodDisease(curFoodName,number));
                        List<String> doEatFoodDiseaseList = new ArrayList<>();
                        for (DiseaseEntity diseaseEntity1:doEatDisease){
                            if(!doEatFoodDiseaseList.contains(diseaseEntity1.getName())){
                                doEatFoodDiseaseList.add(diseaseEntity1.getName());
                            }
                        }
                        sqlResult.put("food_do_disease",doEatFoodDiseaseList);
                    }
                }
            }
            //每次循环给答案追加

            sb.append(AnswerUtil.getAnswer(questionType,sqlResult));
//            System.out.println(sqlResult);//*****
            sb.append("\n");
        }
        /*
        查数据
         */

        //***********************************************************************************
        /**
         *@author lmh
         *@date 2023/3/26
         *@desc AnswerUtil的使用，组装成答案String
         * 放到上面了
         */
//        for (String s:questionTypeList){
//            sb.append(AnswerUtil.getAnswer(s,sqlResult));
//            sb.append("\\n");
//        }
        return sb.toString();
    }

    /**
     *@author lmh
     *@date 2023/4/10
     *@desc 只分页查询疾病实体
     */
    @Override
    public List<DiseaseEntity> getPageDisease(int page, int size) {
        return diseaseRepository.getNumDisease(page,size);
    }

    @Override
    public Integer getDiseaseNum(){
        return diseaseRepository.getDiseaseNum();
    }

}
